package com.example.demo.yzy.server.impl;

import com.example.demo.exception.ExceptionEnum;
import com.example.demo.exception.throwtype.RunException;
import com.example.demo.yzy.dao.Person;
import com.example.demo.yzy.dao.PersonQuery;
import com.example.demo.yzy.mapper.PersonMapper;
import com.example.demo.yzy.server.TestServer;
import com.example.demo.yzy.vo.QueryVo;
import com.example.demo.yzy.vo.TestVo;
import com.example.demo.yzy.vo.UpdateVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @description: TODO
* @author 杨镇宇
* @date 2022/3/24 14:59
* @version 1.0
*/
@Service
public class TestSeverImpl implements TestServer {
    private static Logger log = LoggerFactory.getLogger(TestSeverImpl.class);

    @Autowired
    private PersonMapper mapper;
    /**
     * 复制相同的属性到新对象里面
     *
     * @param source 有数据的对象
     * @param target 新对象
     * @param <T>    泛型
     * @return 新对象
     */
    public static <T> T copy(Object source, T target) throws NoSuchFieldException, IllegalAccessException {
        if (Map.class.isAssignableFrom(source.getClass())) {
            Class clazz = target.getClass();
            Map<String,? extends Object> map = (Map<String, ? extends Object>) source;
            Set keys = map.keySet();
            for (Object key:keys){
                Field field = clazz.getDeclaredField(key.toString());
                Object value = map.get(key);
                field.setAccessible(true);
                field.set(target,value);
            }
        } else {
            BeanUtils.copyProperties(source,target);
        }
        return target;
    }
    /**
     * 复制相同的属性到新对象里面
     *
     * @param sourceList 有数据的对象集合
     * @param clz        新对象的类型
     * @param <T>        泛型
     * @return 新对象
     */
    public static <T> List<T> copyList(List<?> sourceList, Class<T> clz) {
        List<T> finalResult = new ArrayList<>(sourceList.size());
        ;
        sourceList.forEach(v -> {
            try {
                T obj = clz.getDeclaredConstructor().newInstance();
                copy(v, obj);
                finalResult.add(obj);
            } catch (Exception e) {
                log.error("复制相同的属性到新对象里面失败",e);
            }
        });
        return finalResult;
    }
    @Override
    @Transactional(rollbackFor =  {Exception.class,RunException.class})
    public int insert(TestVo vo)  {
        Person person = new Person();
        int i = 0;
        try {
            copy(vo,person);
             i = mapper.insertSelective(person);
        }catch (Exception e){
            log.error("错误",e);
            throw new RunException(ExceptionEnum.INSERT_ERROR);
        }
        return i;
    }

    //根据name条件修改
    @Override
    @Transactional(rollbackFor = {Exception.class,RunException.class})
    public int update(UpdateVo vo) {
        Person person = new Person();
        PersonQuery personQuery = new PersonQuery();
        PersonQuery.Criteria criteria = personQuery.createCriteria();
        criteria.andNameLike("%"+vo.getName()+"%");
        int i = 0;
        try {
            copy(vo,person);
            i = mapper.updateByExampleSelective(person,personQuery);
        }catch (Exception e){
            log.error("错误",e);
            throw new RunException(ExceptionEnum.INSERT_ERROR);
        }
        return i;    }

    @Override
    public int updateById(UpdateVo vo) {
        Person person = new Person();
        int i = 0;
        try {
            copy(vo,person);
            i = mapper.updateByPrimaryKey(person);
        }catch (Exception e){
            throw new RunException(ExceptionEnum.INSERT_ERROR);
        }
        return i;    }

    @Override
    public List<Person> select(QueryVo vo) {
        PersonQuery personQuery = new PersonQuery();
        PersonQuery.Criteria criteria = personQuery.createCriteria();
        if (StringUtils.isNotBlank(vo.getName())){
            criteria.andNameEqualTo(vo.getName());
        }
        if (null != vo.getId()){
            criteria.andIdEqualTo(vo.getId());
        }
        if (null != vo.getAge()){
            criteria.andAgeEqualTo(vo.getAge());
        }
        return mapper.selectByExample(personQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delete(UpdateVo vo) {
        return mapper.deleteByPrimaryKey(vo.getId());

    }

    @Override
    public int deleteByName(UpdateVo vo) {
        PersonQuery personQuery = new PersonQuery();
        PersonQuery.Criteria criteria = personQuery.createCriteria();
        criteria.andNameEqualTo(vo.getName());
        return mapper.deleteByExample(personQuery);
    }
}
